package org.hank.compose_yyzs.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.orhanobut.logger.Logger
import com.tencent.mmkv.MMKV
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import org.hank.compose_yyzs.bean.ProjectBean
import org.hank.compose_yyzs.bean.ProjectTreeNode
import org.hank.compose_yyzs.bean.StageBean
import org.hank.compose_yyzs.bean.request.ProjectDto
import org.hank.compose_yyzs.constants.Constants
import org.hank.compose_yyzs.db.dao.ProjectDao
import org.hank.compose_yyzs.http.ApiService
import org.hank.compose_yyzs.bean.HomeProjectBean
import org.hank.compose_yyzs.http.bean.HttpWrapBean
import org.hank.compose_yyzs.ui.paging.simplePager
import org.hank.compose_yyzs.utils.JsonCopy
import org.hank.compose_yyzs.utils.NetWorkUtils
import org.hank.compose_yyzs.utils.toJson
import javax.inject.Inject
import kotlin.random.Random

//  ┏┓　　　┏┓
//┏┛┻━━━┛┻┓
//┃　　　　　　　┃
//┃　　　━　　　┃
//┃　┳┛　┗┳　┃
//┃　　　　　　　┃
//┃　　　┻　　　┃
//┃　　　　　　　┃
//┗━┓　　　┏━┛
//    ┃　　　┃                  神兽保佑
//    ┃　　　┃                  永无BUG！
//    ┃　　　┗━━━┓
//    ┃　　　　　　　┣┓
//    ┃　　　　　　　┏┛
//    ┗┓┓┏━┳┓┏┛
//      ┃┫┫　┃┫┫
//      ┗┻┛　┗┻┛
/**
 *@auth: Hank
 *邮箱: cs16xiaoc1@163.com
 *创建时间: 2023/11/9 10:59
 *描述:
 */
@HiltViewModel
class ProjectViewModel @Inject constructor(
    var apiService: ApiService,
    var projectDao: ProjectDao
) :
    ViewModel() {
    private val _viewEvents = Channel<ProjectViewEvent>(Channel.BUFFERED)
    val viewEvents = _viewEvents.receiveAsFlow()
    var isRefreshingAll = MutableStateFlow(false)
    var isRefreshingComplete = MutableStateFlow(false)
    var isRefreshingProgress = MutableStateFlow(false)
    var lastDeptIdAll = MutableStateFlow(0L)
    var lastDeptIdComplete = MutableStateFlow(0L)
    var lastDeptIdPregress = MutableStateFlow(0L)

    var pagerAll = getPager(0)
    var pagerComplete = getPager(1)
    var pagerProgress = getPager(2)

    var projectName = MutableStateFlow("")
    var areaName = MutableStateFlow("")

    fun getProjectTree() {
        viewModelScope.launch {
            flow { emit(apiService.getProjectTree()) }
                .catch {
                    _viewEvents.send(ProjectViewEvent.ErrorMessage(it.message ?: ""))
                }.collect { projectList ->
                    var time = System.currentTimeMillis()
                    var copyList =
                        Gson().fromJson<MutableList<ProjectTreeNode>>(projectList.data.toJson(),
                            object : TypeToken<MutableList<ProjectTreeNode>>() {}.type
                        )
                    Logger.d("get project Tree")
                    withContext(Dispatchers.IO) {
                        projectDao.delAll()
                        var deptId = MMKV.defaultMMKV().getLong(Constants.DEPTID, 0L)
                        //没有选中项目，默认选择所有树结构第一个
                        var defaultProjectTree =
                            MMKV.defaultMMKV().getString(Constants.CURRENT_PROJECTTREE, "")
                        addParentToChildren(copyList[0])
                        addAreaName(copyList[0])

                        if (deptId == 0L || defaultProjectTree.isNullOrEmpty())
                            setDept(copyList[0].children[0])

                        defaultProjectTree =
                            MMKV.defaultMMKV().getString(Constants.CURRENT_PROJECTTREE, "")
                        val selectProject =
                            Gson().fromJson(defaultProjectTree, ProjectTreeNode::class.java)
                        Logger.d("invoke time = ${System.currentTimeMillis() - time}")
                        projectName.emit(selectProject.name)
                        areaName.emit(selectProject.areaName ?: "")
                        projectList.data[0].children.forEach {
                            projectDao.insert(it)
                        }
                    }
                }
        }
    }

    private fun addParentToChildren(projectTreeNode: ProjectTreeNode) {
        if (!projectTreeNode.children.isNullOrEmpty()) {
            for (child in projectTreeNode.children!!) {
                child.parent = projectTreeNode
                addParentToChildren(child)
            }
        }
    }

    private fun addAreaName(projectTreeNode: ProjectTreeNode) {
        if (projectTreeNode.parent != null) {
            projectTreeNode.areaName = projectTreeNode.parent!!.name
            if (projectTreeNode.parent!!.parent != null)
                projectTreeNode.areaName =
                    projectTreeNode.parent!!.parent!!.name + "-" + projectTreeNode.parent!!.name
        }
        if (!projectTreeNode.children.isNullOrEmpty()) {
            projectTreeNode.children!!.forEach { addAreaName(it) }
        }
    }

    private fun setDept(projectTreeNode: ProjectTreeNode) {
        if (!projectTreeNode.children.isNullOrEmpty()) {
            setDept(projectTreeNode.children[0])
        } else {
            removeParent(projectTreeNode)
            MMKV.defaultMMKV().putLong(Constants.DEPTID, projectTreeNode.id)
            MMKV.defaultMMKV().putString(Constants.CURRENT_PROJECTTREE, projectTreeNode.toJson())
        }
    }

    private fun removeParent(projectTreeNode: ProjectTreeNode) {
        if (!projectTreeNode.children.isNullOrEmpty()) {
            projectTreeNode.children.forEach {
                removeParent(it)
            }
        }
        projectTreeNode.parent = null
    }

    fun getPager(status: Int): Flow<PagingData<HomeProjectBean>> {
        return simplePager(
            if (status == 0) isRefreshingAll else if (status == 1) isRefreshingComplete else isRefreshingProgress,
            secondAction = { it ->
                var projectIdsList = it.asSequence().map { it.id }.toMutableList()
                apiService.getProjectRoomCount(
                    Gson().toJson(projectIdsList).toRequestBody("application/json".toMediaType())
                )
            },
            secondMerge = { list1, list2 ->
                list1.forEach { homeProject ->
                    list2.forEach { stage ->
                        if (stage.projectId == homeProject.id) {
                            homeProject.totalData = stage.totalData
                            var random = Random.nextInt(0, 3)
//                        homeProject.status = stage.status
                            homeProject.status = random
                        }
                    }
                }
                list1.asSequence().filter { if (status != 0) it.status == status - 1 else true }
                    .toMutableList()
            }) {
            var deptId = MMKV.defaultMMKV().getLong(Constants.DEPTID, 0L)
            when (status) {
                0 ->
                    lastDeptIdAll.value = deptId

                1 ->
                    lastDeptIdComplete.value = deptId

                2 ->
                    lastDeptIdPregress.value = deptId
            }
            apiService.pageProject(ProjectDto(current = it, deptId = deptId))
        }
    }

    suspend fun checkProjectTree(): Boolean {
        return projectDao.getProjectTreeSize() > 0
    }
}

sealed class ProjectViewEvent {
    data class ErrorMessage(val message: String) : ProjectViewEvent()
}